package com.jacky.webflux.jwt.security;

import com.jacky.webflux.jwt.token.JwtTokenComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class JwtAuthenticationManager implements ReactiveAuthenticationManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationManager.class);

    private final JwtTokenComponent jwtTokenComponent;

    public JwtAuthenticationManager(JwtTokenComponent jwtTokenComponent) {
        this.jwtTokenComponent = jwtTokenComponent;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        return Mono.just(authentication)
                .map(auth -> jwtTokenComponent.getClaimsFromToken(auth.getCredentials().toString()))
                .log()
                .onErrorResume(ex -> {
                    LOGGER.error("");
                    return Mono.empty();
                })
                .map(claims -> {
                    List<String> roles = claims.get("roles", List.class);
                    Set<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
                    return new UsernamePasswordAuthenticationToken(claims.getSubject(),
                            "", authorities);
                });
    }
}
